﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Odelle.BlueForest
{
    public class FilterBinder
    {
        public event System.EventHandler FilterUpdated = delegate(Object s, EventArgs e) { };


        Odelle.WoWArmory.Data.CharacterQuery query = new WoWArmory.Data.CharacterQuery();
        public string QueryDelimiter { get { return WoWArmory.Data.CharacterQuery.QueryDelimiter.ToString(); } }
        public string QuerySeparator { get { return WoWArmory.Data.CharacterQuery.QuerySeparator.ToString(); } }

        List<FilterItem> Items = new List<FilterItem>();

        Odelle.WoWArmory.Data.CharacterData[] characters = null;

        public Odelle.WoWArmory.Data.CharacterQuery Query
        {
            get { return query; }
        }
        public string Prefilter { get; set; }


        public FilterBinder()
        {
            this.Prefilter = "";
        }

        public void Add(FilterItem item)
        {
            Items.Add(item);
            item.FilterNameChanged += new System.EventHandler(this.FilterItems_FilterNameChanged);
            item.ValueChanged += new System.EventHandler(this.FilterItems_ValueChanged);
        }

        public void Remove(FilterItem item)
        {
            item.FilterNameChanged -= new System.EventHandler(this.FilterItems_FilterNameChanged);
            item.ValueChanged -= new System.EventHandler(this.FilterItems_ValueChanged);
            Items.Remove(item);
        }

        public void AttachCharacterDataSet(Odelle.WoWArmory.Data.CharacterData[] characterDataSet)
        {
            characters = characterDataSet;
        }
        public void DetachCharacterDataSet()
        {
            characters = null;
        }

        private void FilterItems_FilterNameChanged(object sender, EventArgs e)
        {
            if (isUpdateNames)
                return;

            UpdateNames();
        }

        private void FilterItems_ValueChanged(object sender, EventArgs e)
        {
            if (isUpdateNames)
                return;
            if (isUpdateValues)
                return;

            UpdateValues();

            FilterUpdated(sender, EventArgs.Empty);
        }

        private bool isUpdateNames = false;
        public void UpdateNames()
        {
            isUpdateNames = true;

            query.Clear();

            //--- pre filters
            query.AddFilterEntries(this.Prefilter);

            //--- gui filters
            for (int i = 0; i < Items.Count; ++i)
            {
                if (Items[i].FilterName == "")
                {
                    Items[i].HasError = false;
                }
                else
                {
                    bool notDupe = query.Add(Items[i].FilterName, Items[i].FilterValue);

                    if (notDupe)
                    {
                    }
                    Items[i].HasError = !notDupe;
                }
            }

            isUpdateNames = false;
        }

        private bool isUpdateValues = false;
        public void UpdateValues()
        {
            isUpdateValues = true;

            UpdateQueryValues();

            for (int i = 0; i < Items.Count; ++i)
            {
                if (Items[i].FilterName != "" && Items[i].HasError == false)
                {
                    string prev = Items[i].Value;
                    Items[i].Clear();

                    if (characters != null && characters.Length > 0)
                    {
                        Items[i].AddRange(query.GetValuesList(Items[i].FilterName, characters));
                    }

                    Items[i].Value = prev;
                }
            }

            isUpdateValues = false;
        }

        public void UpdateQueryValues()
        {
            for (int i = 0; i < Items.Count; ++i)
            {
                query.SetValue(Items[i].FilterName, Items[i].FilterValue);

                if (Items[i].FilterEntry != "")
                {
                    query.SetEnabled(Items[i].FilterName, true);
                }
                else
                {
                    query.SetEnabled(Items[i].FilterName, false);
                }
            }
        }

        public void ClearQueryValues()
        {
            isUpdateNames = true;
            for (int i = 0; i < Items.Count; ++i)
            {
                Items[i].Operator = "=";
                Items[i].Value = "*";
            }
            isUpdateNames = false;

            UpdateValues();
        }

        public string[] GetValuesList(string name)
        {
            if (characters == null)
                return null;

            UpdateQueryValues();

            return query.GetValuesList(name, characters);
        }

        public Odelle.WoWArmory.Data.CharacterData[] GetCharacterDataList()
        {
            return query.Query(characters);
        }
    }
}
